package com.dawn.module.hospital.service;

import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSON;
import com.dawn.framework.common.exception.ServerException;
import com.dawn.framework.common.pojo.CommonResult;
import com.dawn.framework.common.util.http.HttpUtils;
import com.dawn.module.hospital.config.CDBPayConfig;
import com.dawn.module.hospital.enums.ErrorCodeConstants;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;

/**
 * @description:
 * @author: cnsu-cmh
 * @time: 2024/8/7 23:10
 */
@Slf4j
@Component
public class CDBPayUtils {

    private static final Integer ERROR_CODE = ErrorCodeConstants.PAY_ERROR.getCode();

    private final static String UNIFIED_ORDER_URL = "yncdb/pay/unifiedOrder"; // 统一下单
    private final static String REFUND_ORDER_URL = "yncdb/pay/refund"; // 退费
    private final static String QUERY_ORDER_URL = "yncdb/pay/query"; // 查询
    private final static String QUERY_CHS_ORDER_URL = "yncdb/pay/chs/query"; // 查询
    private final static String QUERY_REFUND_ORDER_URL = "yncdb/pay/refund/query"; // 退费订单查询
    private final static String QUERY_PAY_ORDER_URL = "yncdb/pay/statics/order/query"; // 根据订单号查询订单信息


    public final static String ALI = "ALI";

    public final static String ALICHS = "ALICHS";

    public final static String WX = "WX";
    public final static String WX_CHS = "WX_CHS";

    public final static String ABC = "ABC";

    public final static String DAWN_PAY = "DAWN_PAY";

    private volatile static CDBPayConfig cdbCfg;

    static {
        if (null == cdbCfg) {
            synchronized (CDBPayConfig.class) {
                if (null == cdbCfg) {
                    cdbCfg = SpringUtil.getBean(CDBPayConfig.class);
                }
            }
        }
    }

    public static CDBPayUtils instance() {
        return new CDBPayUtils();
    }

    private HashMap<String,Object> params;

    public CDBPayUtils build(String payWay){
        this.params = packageCommonParam(payWay);
        return this;
    }

    private HashMap<String, Object> getParams() {
        if(CollectionUtils.isEmpty(this.params)) {
            throw new ServerException(ERROR_CODE, "支付工具类未构建，请先build");
        }
        return params;
    }

    /**
     * 功能描述: 获取微信公众号支付参数
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:15
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @param openid:
     * @return: com.dawn.hospital.api.utils.CommonResult
     */
    public CommonResult wxJsapiPay(String orderNo, String orderTitle, String payMent, String body, String openid) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getWx().getWxCode());
        params.put("notifyUrl",cdbCfg.getNotifyUrl());
        params.put("openid",openid);
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 获取网页支付二维码地址
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:20
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @return: com.dawn.hospital.api.utils.CommonResult
     */
    public CommonResult wapPay(String orderNo, String orderTitle, String payMent, String body) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getWx().getWapCode());
        params.put("notifyUrl",cdbCfg.getNotifyUrl());
        params.put("terminalNo",cdbCfg.getAbc().getTerminalNo());
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 条码付
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:22
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @param authCode:
     * @return: java.util.HashMap
     */
    public CommonResult barPay(String orderNo, String orderTitle, String payMent, String body, String authCode) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getWx().getBarCode());
        params.put("notifyUrl",cdbCfg.getNotifyUrl());
        params.put("authCode",authCode);
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 支付宝当面付支付二维码
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:20
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @return: com.dawn.hospital.api.utils.CommonResult
     */
    public CommonResult aliQrPay(String orderNo, String orderTitle, String payMent, String body) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getAli().getQrCode());
        params.put("notifyUrl",cdbCfg.getNotifyUrl());
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }


    /**
     * 功能描述: 支付宝生活号当面付JSAPI支付
     * @auther: cnsu-cmh
     * @date: 2022-10-24 18:17
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @param userId:
     * @return: com.dawn.hospital.api.utils.CommonResult
     */
    public CommonResult aliJsapiPay(String orderNo, String orderTitle, String payMent, String body, String userId) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getAli().getJsapiCode());
        params.put("notifyUrl",cdbCfg.getNotifyUrl());
        params.put("buyerUserId",userId);
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 支付宝生医保移动支付
     * @auther: cnsu-cmh
     * @date: 2022-10-24 18:17
     * @param orderNo:
     * @param orderTitle:
     * @param payMent:
     * @param body:
     * @param userId:
     * @return: com.dawn.hospital.api.utils.CommonResult
     */
    public CommonResult aliChsPay(String orderNo, String orderTitle, String payMent, String body, String userId, HashMap chsParams) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getAliChs().getChsCode());
        params.put("notifyUrl",cdbCfg.getNotifyChsUrl());
        params.put("buyerUserId",userId);
        params.putAll(chsParams);
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 单笔退款
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:26
     * @param orderNo:
     * @param refundOrderNo:
     * @param refundAmount:
     * @param refundReason:
     * @return: java.util.HashMap
     */
    public CommonResult refundOrder(String orderNo, String refundOrderNo, String refundAmount, String refundReason) {
        HashMap<String,Object> params = getParams();
        params.put("refundAmount",refundAmount);
        params.put("refundReason",refundReason);
        params.put("mchOrderNo",orderNo);
        params.put("mchRefundNo",refundOrderNo);
        return HttpUtils.postForm(cdbCfg.getUrl() + REFUND_ORDER_URL, params);
    }

    /**
     * 功能描述: 订单查询
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:27
     * @param orderNo:
     * @return: java.util.HashMap
     */
    public CommonResult query(String orderNo) {
        HashMap<String,Object> params = getParams();
        params.put("mchOrderNo",orderNo);
        return HttpUtils.postForm(cdbCfg.getUrl() + QUERY_ORDER_URL, params);
    }

    /**
     * 功能描述: 根据订单号查询订单信息
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:27
     * @param orderNo:
     * @return: java.util.HashMap
     */
    public CommonResult queryOrderInfo(String orderNo) {
        HashMap<String,Object> params = new HashMap<>();
        params.put("orderNo",orderNo);
        return HttpUtils.postForm(cdbCfg.getUrl() + QUERY_PAY_ORDER_URL, params);
    }

    /**
     * 功能描述: 订单查询
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:27
     * @param orderNo:
     * @return: java.util.HashMap
     */
    public CommonResult chsQuery(String orderNo) {
        HashMap<String,Object> params = getParams();
        params.put("mchOrderNo",orderNo);
        return HttpUtils.postForm(cdbCfg.getUrl() + QUERY_CHS_ORDER_URL, params);
    }


    /**
     * 功能描述: 退款订单查询
     * @auther: cnsu-cmh
     * @date: 2022-12-02 14:49
     * @param payOrderId:
     * @return: java.util.HashMap
     */
    public CommonResult refundQuery(String payOrderId) {
        HashMap<String,Object> params = getParams();
        params.put("payOrderId",payOrderId);
        return HttpUtils.postForm(cdbCfg.getUrl() + QUERY_REFUND_ORDER_URL, params);

    }


    /**
     * 功能描述:  医保移动支付单笔退款
     * @auther: cnsu-cmh
     * @date: 2022-12-02 15:26
     * @param orderNo:
     * @param refundOrderNo:
     * @param refundAmount:
     * @param refundReason:
     * @return: java.util.HashMap
     */
    public CommonResult chsRefundOrder(String orderNo, String refundOrderNo, String refundAmount, String refundReason, HashMap chsParams) {
        HashMap<String,Object> params = getParams();
        params.put("refundAmount",refundAmount);
        params.put("refundReason",refundReason);
        params.put("mchOrderNo",orderNo);
        params.put("mchRefundNo",refundOrderNo);
        params.putAll(chsParams);
        return HttpUtils.postForm(cdbCfg.getUrl() + REFUND_ORDER_URL, params);
    }

    public CommonResult wxChsJsapiPay(String orderNo, String orderTitle, String payMent, String body, String openid, HashMap chsParams) {
        HashMap<String,Object> params = packagePayParam(payMent,orderNo,orderTitle,body);
        params.put("wayCode",cdbCfg.getWxChs().getJsapiCode());
        params.put("notifyUrl",cdbCfg.getWxChs().getNotifyUrl());
        params.put("returnUrl",cdbCfg.getWxChs().getReturnUrl() + "?orderNumber="+orderNo);
        params.put("openid",openid);
        params.putAll(chsParams);
        return HttpUtils.postForm(cdbCfg.getUrl() + UNIFIED_ORDER_URL, params);
    }

    /**
     * 功能描述: 组装订单数据
     * @auther: cnsu-cmh
     * @date: 2022-10-21 17:29
     * @param brid:
     * @param name:
     * @param mzh:
     * @param idCardNo:
     * @param djh:
     * @return: java.lang.String
     */
    public static String packageBody(String brid, String name, String mzh, String idCardNo, String djh) {
        HashMap<String,Object> params = new HashMap<>();
        params.put("BRID",brid);
        params.put("BRXM",name);
        params.put("MZH",mzh);
        params.put("SFZH", StringUtils.hasLength(idCardNo) ? idCardNo : "");
        params.put("NO", StringUtils.hasLength(djh) ? djh : "");
        return JSONUtil.toJsonStr(params);
    }

    private HashMap<String,Object> packagePayParam(String amount, String orderNo, String orderTitle,String body) {
        HashMap<String,Object> params = getParams();
        params.put("divisionMode",0);
        params.put("amount",amount);
        params.put("mchOrderNo",orderNo);
        params.put("orderTitle",orderTitle);
        params.put("orderBody",body);
        return params;
    }

    private HashMap<String,Object> packageCommonParam(String payWay) {
        HashMap<String,Object> params = new HashMap<>();
        if(payWay.equals(WX)) {
            params.put("appId",cdbCfg.getWx().getAppid());
            params.put("mchNo",cdbCfg.getWx().getMchNo());
            params.put("appSecret",cdbCfg.getWx().getAppSecret());
        }else if(payWay.equals(ABC)){
            params.put("appId",cdbCfg.getAbc().getAppid());
            params.put("mchNo",cdbCfg.getAbc().getMchNo());
            params.put("appSecret",cdbCfg.getAbc().getAppSecret());
        }else if(payWay.equals(WX_CHS)){
            params.put("appId",cdbCfg.getWxChs().getAppid());
            params.put("mchNo",cdbCfg.getWxChs().getMchNo());
            params.put("appSecret",cdbCfg.getWxChs().getAppSecret());
        }else if(payWay.equals(ALI)){
            params.put("appId",cdbCfg.getAli().getAppid());
            params.put("mchNo",cdbCfg.getAli().getMchNo());
            params.put("appSecret",cdbCfg.getAli().getAppSecret());
        }else if(payWay.equals(ALICHS)){
            params.put("appId",cdbCfg.getAliChs().getAppid());
            params.put("mchNo",cdbCfg.getAliChs().getMchNo());
            params.put("appSecret",cdbCfg.getAliChs().getAppSecret());
        }else if(payWay.equals(DAWN_PAY)){
            params.put("appId",cdbCfg.getDawnPay().getAppid());
            params.put("mchNo",cdbCfg.getDawnPay().getMchNo());
            params.put("appSecret",cdbCfg.getDawnPay().getAppSecret());
        }
        return params;
    }

}
